import { IRect, ISize, IVec2 } from "../../util/Defined";
import { TypeUtil } from "../../util/TypeUtil";
import { Vec2 } from "./Vec2";

/**
 * 矩形 xy零点为左下 (-1,-1)
 */
export class Rect extends Vec2 implements IRect {

    /** 零点 */
    static readonly ZERO = TypeUtil.readonlyType(new Rect(0, 0, 0, 0));
    /** 临时变量 */
    static readonly T = new Rect();
    /** 临时变量 */
    static readonly T2 = new Rect();
    /** 临时变量 */
    static readonly T3 = new Rect();
    /** 临时变量 */
    static readonly T4 = new Rect();
    /** 临时变量 */
    static readonly T5 = new Rect();

    /** 
     * 复制矩形生成一个新的矩形
     */
    static copyRect(rect: Readonly<IRect>) {
        return new Rect(rect.x, rect.y, rect.width, rect.height);
    }

    /**
     * 设置大小
     * @param out 
     * @param width 
     * @param height 
     */
    static setSize<T extends ISize>(out: T, width: number, height: number) {
        out.width = width;
        out.height = height;
        return out;
    }

    /**
     * 设置大小
     * @param out 
     * @param size
     */
    static setSizeTo<T extends ISize>(out: T, size: Readonly<ISize>) {
        out.width = size.width;
        out.height = size.height;
        return out;
    }

    /**
     * 设置矩形
     * @param out 
     * @param x 
     * @param y 
     * @param width
     * @param height
     */
    static setRect<T extends IRect>(out: T, x: number, y: number, width: number, height: number) {
        out.x = x;
        out.y = y;
        out.width = width;
        out.height = height;
        return out;
    }

    /**
     * 设置矩形
     * @param out 
     * @param pos
     */
    static setRectTo<T extends IRect>(out: T, rect: Readonly<IRect>) {
        out.x = rect.x;
        out.y = rect.y;
        out.width = rect.width;
        out.height = rect.height;
        return out;
    }

    /**
     * 增量大小
     * @param out 
     * @param width 
     * @param height 
     */
    static addSize<T extends IRect>(out: T, width: number, height: number) {
        out.width += width;
        out.height += height;
        return out;
    }

    /**
     * 增量大小
     * @param size
     */
    static addSizeTo<T extends IRect>(out: T, size: Readonly<ISize>) {
        out.width += size.width;
        out.height += size.height;
        return out;
    }

    /**
     * 增量矩形
     * @param out 
     * @param x 
     * @param y 
     * @param width
     * @param height
     */
    static addRect<T extends IRect>(out: T, x: number, y: number, width: number, height: number) {
        out.x += x;
        out.y += y;
        out.width += width;
        out.height += height;
        return out;
    }

    /**
     * 增量矩形
     * @param out 
     * @param pos
     */
    static addRectTo<T extends IRect>(out: T, rect: Readonly<IRect>) {
        out.x += rect.x;
        out.y += rect.y;
        out.width += rect.width;
        out.height += rect.height;
        return out;
    }

    /**
     * 判断矩形是否包含指定的点
     * @param rect
     * @param pos
     */
    static containsPos(rect: IRect, pos: Readonly<IVec2>) {
        return (rect.x <= pos.x
            && rect.y <= pos.y
            && rect.x + rect.width >= pos.x
            && rect.y + rect.height >= pos.y);
    }

    /**
     * 判断矩形是否包含指定矩形
     * @param rect 
     * @param other 
     */
    static containsRect(rect: Readonly<IRect>, other: Readonly<IRect>) {
        return (rect.x <= other.x
            && rect.y <= other.y
            && rect.x + rect.width >= other.x + other.width
            && rect.y + rect.height >= other.y + other.height);
    }

    /**
     * 将矩形设置为与指定矩形的重叠部分
     * @param out
     * @param rect
     */
    static intersectionRect<T extends IRect>(out: T, rect: Readonly<IRect>) {
        const axMin = out.x;
        const ayMin = out.y;
        const axMax = out.x + out.width;
        const ayMax = out.y + out.height;
        const bxMin = rect.x;
        const byMin = rect.y;
        const bxMax = rect.x + rect.width;
        const byMax = rect.y + rect.height;
        out.x = Math.max(axMin, bxMin);
        out.y = Math.max(ayMin, byMin);
        out.width = Math.min(axMax, bxMax) - out.x;
        out.height = Math.min(ayMax, byMax) - out.y;
        return out;
    }

    constructor(
        x = 0, y = 0,
        public width = 0,
        public height = 0) {
        super(x, y);
    }

    get maxX() {
        return this.x + this.width;
    }

    get maxY() {
        return this.y + this.height;
    }

    /** 
     * 复制当前矩形生成一个新的矩形
     */
    copyRect() {
        return Rect.copyRect(this);
    }

    /**
     * 设置大小
     * @param width 
     * @param height 
     */
    setSize(width: number, height: number) {
        return Rect.setSize(this, width, height);
    }

    /**
     * 设置大小
     * @param width 
     * @param height 
     */
    setSizeTo(size: Readonly<ISize>) {
        return Rect.setSizeTo(this, size);
    }

    /**
     * 设置矩形
     * @param x 
     * @param y 
     * @param width
     * @param height
     */
    setRect(x: number, y: number, width: number, height: number) {
        return Rect.setRect(this, x, y, width, height);
    }

    /**
     * 设置矩形
     * @param pos
     */
    setRectTo(rect: Readonly<IRect>) {
        return Rect.setRectTo(this, rect);
    }

    /**
     * 增量大小
     * @param width 
     * @param height 
     */
    addSize(width: number, height: number) {
        return Rect.addSize(this, width, height);
    }

    /**
     * 增量大小
     * @param size
     */
    addSizeTo(size: Readonly<ISize>) {
        return Rect.addSizeTo(this, size);
    }

    /**
     * 增量矩形
     * @param x 
     * @param y 
     * @param width
     * @param height
     */
    addRect(x: number, y: number, width: number, height: number) {
        return Rect.addRect(this, x, y, width, height);
    }

    /**
     * 增量矩形
     * @param pos
     */
    addRectTo(rect: Readonly<IRect>) {
        return Rect.addRectTo(this, rect);
    }

    /**
     * 判断当前矩形是否包含指定的点。
     * @param pos 
     */
    containsPos(pos: Readonly<IVec2>) {
        return Rect.containsPos(this, pos);
    }

    /**
     * 判断矩形是否包含指定矩形
     * @param other 
     */
    containsRect(other: Readonly<IRect>) {
        return Rect.containsRect(this, other);
    }

    /**
     * 将矩形设置为与指定矩形的重叠部分
     * @param rect
     */
    intersectionRect(rect: Readonly<IRect>) {
        return Rect.intersectionRect(this, rect);
    }

}